#include "modbusmaster.h"
#include "../utils/logger.h"
#include <QThread>
#include <QElapsedTimer>
#include <QMutexLocker>

ModbusMaster::ModbusMaster(QSerialPort *serialPort, QObject *parent)
    : QObject(parent), m_serialPort(serialPort)
{
    Logger::instance()->log(LogLevel::Info, "ModbusMaster: Modbus主站初始化");
}

ModbusMaster::~ModbusMaster()
{
    Logger::instance()->log(LogLevel::Info, "ModbusMaster: Modbus主站销毁");
}

// 读取保持寄存器
ModbusMaster::ModbusResponse ModbusMaster::readHoldingRegisters(quint8 slaveId,
                                                                quint16 startAddress, quint16 quantity, int timeout)
{
    QMutexLocker locker(&m_mutex);

    ModbusResponse response;
    response.success = false;
    response.slaveId = slaveId;
    response.functionCode = FUNCTION_CODE_READ_HOLDING_REGISTERS;

    // 检查串口是否可用
    if (!m_serialPort || !m_serialPort->isOpen())
    {
        response.errorMessage = "串口未打开";
        Logger::instance()->log(LogLevel::Error,
                                QString("ModbusMaster: 站号 %1: %2").arg(slaveId).arg(response.errorMessage));
        emit communicationError(slaveId, response.errorMessage);
        return response;
    }

    // 参数验证
    if (slaveId < 1 || slaveId > 247)
    {
        response.errorMessage = QString("无效的从站地址: %1").arg(slaveId);
        Logger::instance()->log(LogLevel::Error, QString("ModbusMaster: %1").arg(response.errorMessage));
        emit communicationError(slaveId, response.errorMessage);
        return response;
    }

    if (quantity < 1 || quantity > 125)
    {
        response.errorMessage = QString("无效的寄存器数量: %1").arg(quantity);
        Logger::instance()->log(LogLevel::Error, QString("ModbusMaster: %1").arg(response.errorMessage));
        emit communicationError(slaveId, response.errorMessage);
        return response;
    }

    // 清空串口缓冲区
    m_serialPort->clear();

    // 构建请求帧
    QByteArray request = buildRequest(slaveId, FUNCTION_CODE_READ_HOLDING_REGISTERS,
                                      startAddress, quantity);

    Logger::instance()->log(LogLevel::Debug,
                            QString("ModbusMaster: 站号 %1: 发送请求 0x%2").arg(slaveId).arg(QString(request.toHex())));

    // 发送请求
    qint64 bytesWritten = m_serialPort->write(request);
    if (bytesWritten != request.size())
    {
        response.errorMessage = "发送请求失败";
        Logger::instance()->log(LogLevel::Error,
                                QString("ModbusMaster: 站号 %1: %2").arg(slaveId).arg(response.errorMessage));
        emit communicationError(slaveId, response.errorMessage);
        return response;
    }

    m_serialPort->flush();

    // 等待响应（期望长度：地址(1) + 功能码(1) + 字节数(1) + 数据(quantity*2) + CRC(2)）
    int expectedLength = 5 + quantity * 2;
    QByteArray responseData = waitForResponse(expectedLength, timeout);

    if (responseData.isEmpty())
    {
        response.errorMessage = "接收响应超时";
        Logger::instance()->log(LogLevel::Warning,
                                QString("ModbusMaster: 站号 %1: %2").arg(slaveId).arg(response.errorMessage));
        emit communicationError(slaveId, response.errorMessage);
        return response;
    }

    Logger::instance()->log(LogLevel::Debug,
                            QString("ModbusMaster: 站号 %1: 接收响应 0x%2").arg(slaveId).arg(QString(responseData.toHex())));

    // 解析响应
    response = parseResponse(responseData);

    if (response.success)
    {
        Logger::instance()->log(LogLevel::Debug,
                                QString("ModbusMaster: 站号 %1: 成功读取 %2 个寄存器").arg(slaveId).arg(response.data.size()));
        emit responseReceived(slaveId, response.data);
    }
    else
    {
        Logger::instance()->log(LogLevel::Error,
                                QString("ModbusMaster: 站号 %1: %2").arg(slaveId).arg(response.errorMessage));
        emit communicationError(slaveId, response.errorMessage);
    }

    return response;
}

// 读取电表数据
ModbusMaster::ModbusResponse ModbusMaster::readMeterData(quint8 slaveId, int timeout)
{
    // PM2220电表的6个基础参数地址：
    // 0x0000: Ua (A相电压)
    // 0x0002: Ub (B相电压)
    // 0x0004: Uc (C相电压)
    // 0x0006: Ia (A相电流)
    // 0x0008: Ib (B相电流)
    // 0x000A: Ic (C相电流)
    // 每个参数占用2个字节（1个寄存器），共6个寄存器

    return readHoldingRegisters(slaveId, 0x0000, 6, timeout);
}

// 设置串口
void ModbusMaster::setSerialPort(QSerialPort *serialPort)
{
    QMutexLocker locker(&m_mutex);
    m_serialPort = serialPort;
}

// 构建请求
QByteArray ModbusMaster::buildRequest(quint8 slaveId, quint8 functionCode,
                                      quint16 startAddress, quint16 quantity)
{
    QByteArray request;

    // 从站地址
    request.append(static_cast<char>(slaveId));

    // 功能码
    request.append(static_cast<char>(functionCode));

    // 起始地址（高字节在前）
    request.append(static_cast<char>((startAddress >> 8) & 0xFF));
    request.append(static_cast<char>(startAddress & 0xFF));

    // 寄存器数量（高字节在前）
    request.append(static_cast<char>((quantity >> 8) & 0xFF));
    request.append(static_cast<char>(quantity & 0xFF));

    // CRC16校验（低字节在前）
    quint16 crc = calculateCRC16(request);
    request.append(static_cast<char>(crc & 0xFF));
    request.append(static_cast<char>((crc >> 8) & 0xFF));

    return request;
}

// 解析响应
ModbusMaster::ModbusResponse ModbusMaster::parseResponse(const QByteArray &response)
{
    ModbusResponse result;
    result.success = false;

    // 检查最小长度
    if (response.size() < MIN_RESPONSE_LENGTH)
    {
        result.errorMessage = QString("响应数据长度不足: %1").arg(response.size());
        return result;
    }

    // 验证CRC
    if (!verifyCRC16(response))
    {
        result.errorMessage = "CRC校验失败";
        return result;
    }

    // 解析数据
    result.slaveId = static_cast<quint8>(response[0]);
    result.functionCode = static_cast<quint8>(response[1]);

    // 检查是否为异常响应（功能码最高位为1）
    if (result.functionCode & 0x80)
    {
        quint8 exceptionCode = static_cast<quint8>(response[2]);
        result.errorMessage = QString("Modbus异常: 0x%1").arg(exceptionCode, 2, 16, QChar('0'));
        return result;
    }

    // 正常响应
    quint8 byteCount = static_cast<quint8>(response[2]);

    // 检查数据长度
    if (response.size() < 3 + byteCount + 2)
    {
        result.errorMessage = QString("数据长度不匹配，期望 %1，实际 %2")
                                  .arg(3 + byteCount + 2)
                                  .arg(response.size());
        return result;
    }

    // 解析寄存器数据（每个寄存器2字节，高字节在前）
    int registerCount = byteCount / 2;
    for (int i = 0; i < registerCount; ++i)
    {
        int offset = 3 + i * 2;
        quint16 value = (static_cast<quint8>(response[offset]) << 8) |
                        static_cast<quint8>(response[offset + 1]);
        result.data.append(value);
    }

    result.success = true;
    return result;
}

// 计算CRC16
quint16 ModbusMaster::calculateCRC16(const QByteArray &data)
{
    quint16 crc = 0xFFFF;

    for (int i = 0; i < data.size(); ++i)
    {
        crc ^= static_cast<quint8>(data[i]);

        for (int j = 0; j < 8; ++j)
        {
            if (crc & 0x0001)
            {
                crc >>= 1;
                crc ^= 0xA001;
            }
            else
            {
                crc >>= 1;
            }
        }
    }

    return crc;
}

// 验证CRC16
bool ModbusMaster::verifyCRC16(const QByteArray &data)
{
    if (data.size() < 3)
    {
        return false;
    }

    // 提取接收到的CRC（低字节在前）
    quint16 receivedCRC = (static_cast<quint8>(data[data.size() - 1]) << 8) |
                          static_cast<quint8>(data[data.size() - 2]);

    // 计算CRC（不包含最后2字节的CRC）
    QByteArray dataWithoutCRC = data.left(data.size() - 2);
    quint16 calculatedCRC = calculateCRC16(dataWithoutCRC);

    return receivedCRC == calculatedCRC;
}

// 等待响应
QByteArray ModbusMaster::waitForResponse(int expectedLength, int timeout)
{
    QByteArray buffer;
    QElapsedTimer timer;
    timer.start();

    while (timer.elapsed() < timeout)
    {
        // 使用QThread::msleep避免Qt定时器，直接轮询
        if (m_serialPort->bytesAvailable() > 0 || m_serialPort->waitForReadyRead(10))
        {
            buffer.append(m_serialPort->readAll());

            // 检查是否接收到足够的数据
            if (buffer.size() >= expectedLength)
            {
                break;
            }
        }

        // 如果已有数据但长度不足，继续等待
        if (buffer.size() >= MIN_RESPONSE_LENGTH)
        {
            // 检查是否为异常响应（长度较短）
            quint8 functionCode = static_cast<quint8>(buffer[1]);
            if (functionCode & 0x80)
            {
                // 异常响应只有5字节
                if (buffer.size() >= 5)
                {
                    break;
                }
            }
        }

        // 短暂休眠，避免CPU占用过高
        QThread::msleep(1);
    }

    return buffer;
}
